/*************************************************************************//**
 * @file     system_RP2040.c
 * @brief    CMSIS-Core(M) Device Peripheral Access Layer Header File for
 *           Device RP2040
 * @version  V1.0.0
 * @date     5. May 2021
 *****************************************************************************/
/*
 * Copyright (c) 2009-2021 Arm Limited. All rights reserved.
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdint.h>
#include <stdio.h>

#include "rp2040.h"
#include "hardware/clocks.h"
#include "hardware/resets.h"
#include "hardware/gpio.h"
#include "hardware/uart.h"


void abort(void)
{
  while ( 1 )  {
    __asm ( "nop" );
  }
}


void __attribute__((noreturn))  panic(const char *fmt, ...) {
    
    puts("\n*** PANIC ***\n");
    
    if (fmt) {
        puts(fmt);
    }

    abort();
}


/*---------------------------------------------------------------------------
  System Core Clock function
 *---------------------------------------------------------------------------*/
void SystemCoreClockUpdate (void)
{
    return;
}

/*---------------------------------------------------------------------------
  System initialization function
 *---------------------------------------------------------------------------*/
void SystemInit( void )
{
    /**/
    extern char __bss_end;
    extern void miniheap_init(void *ptr, size_t len);
    uintptr_t  tptr;

    /**/
    clocks_init();

#if 0
    /* peri clock, XOSC = 12Mhz */
    clock_hw_t * pclk;
    pclk = &clocks_hw->clk[clk_peri];
    hw_clear_bits( &pclk->ctrl, CLOCKS_CLK_PERI_CTRL_ENABLE_BITS );
    pclk->div = 1 << CLOCKS_CLK_GPOUT0_DIV_INT_LSB;
    pclk->ctrl = CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_XOSC_CLKSRC << CLOCKS_CLK_PERI_CTRL_AUXSRC_LSB;
    hw_set_bits( &pclk->ctrl, CLOCKS_CLK_PERI_CTRL_ENABLE_BITS );
#endif

    /* malloc, free, heap memory manager.. */
    tptr = (uintptr_t)&__bss_end;
    miniheap_init( (void *)tptr, (0x20040000 - tptr) );

    /* undo reset */
    unreset_block_wait( RESETS_RESET_PADS_BANK0_BITS );
    unreset_block_wait( RESETS_RESET_IO_BANK0_BITS );
    unreset_block_wait( RESETS_RESET_UART0_BITS );
  
    /* gpio-12:uart0-tx,  gpio-13:uart0-rx */
    gpio_pull_up( 12 );
    gpio_pull_up( 13 );
    gpio_set_function( 12, GPIO_FUNC_UART );
    gpio_set_function( 13, GPIO_FUNC_UART );

    /* 8N1, 115200 */
    uart_set_baudrate( uart0, 115200 );
    uart_set_format( uart0, 8, 1, UART_PARITY_NONE );
    uart_set_fifo_enabled( uart0, true );
    uart0_hw->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS;
    uart0_hw->dmacr = UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS;
    
    /**/
    return;
}
